package cn.sczc.jh.client.service.synch;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.Service.Listener;
import com.google.common.util.concurrent.Service.State;

import cn.sczc.jh.client.entity.MapImage;
import cn.sczc.jh.client.entity.SynchData;
import cn.sczc.jh.client.exception.BusinessException;
import cn.sczc.jh.client.mapper.sensorHistroy.SensorHistoryMapper;
import cn.sczc.jh.client.mapper.synch.SynchMapper;
import cn.sczc.jh.client.service.equipment.EquipmentPosService;
import cn.sczc.jh.client.service.equipment.EquipmentService;
import cn.sczc.jh.client.service.mapimage.MapImageService;
import cn.sczc.jh.client.service.securityMaterials.SecurityMaterialsService;
import cn.sczc.jh.client.service.sys.PermissionService;
import cn.sczc.jh.client.service.sys.RolePermissionRefService;
import cn.sczc.jh.client.service.sys.RoleService;
import cn.sczc.jh.client.service.sys.UserRoleRefService;
import cn.sczc.jh.client.service.sys.UserService;
import cn.sczc.jh.client.service.team.TeamService;

@Service
@Transactional(rollbackFor = Exception.class)
public class SynchService {
	private boolean synchTaskRunning = false;
	@Autowired
	private SensorHistoryMapper sensorHistroyMapper;
	@Autowired
	private SynchMapper synchMapper;
	@Autowired
	private EquipmentService equipmentService;
	@Autowired
	private EquipmentPosService equipmentPosService;
	@Autowired
	private MapImageService mapImageService;
	@Autowired
	private SecurityMaterialsService securityMaterialsService;
	@Autowired
	private PermissionService permissionService;
	@Autowired
	private RoleService roleService;
	@Autowired
	private RolePermissionRefService rolePermissionRefService;
	@Autowired
	private TeamService teamService;
	@Autowired
	private UserService userService;
	@Autowired
	private UserRoleRefService userRoleRefService;
	@Autowired
	private RestTemplate restTemplate;

	@Value("${jh.cloud.url}")
	private String cloudUrl;

	public String synch(Map<String, Object> params) throws IOException {
		if (synchTaskRunning) {
			throw new BusinessException("正在同步数据。。。");
		}
		int total = sensorHistroyMapper.getSynchSensorDataCount(params);
		if (total == 0) {
			throw new BusinessException("暂无数据可同步！。。。");
		}
		SynchExecutionThreadServiceImpl synchTaskService = new SynchExecutionThreadServiceImpl(sensorHistroyMapper,
				params);
		synchTaskService.addListener(new Listener() {
			@Override
			public void starting() {
				synchTaskRunning = true;
			}

			@Override
			public void running() {
				System.out.println("服务状态为:running");
				synchTaskRunning = true;
			}

			@Override
			public void stopping(State from) {
				System.out.println("服务状态为:stopping");
			}

			@Override
			public void terminated(State from) {
				synchTaskRunning = false;
				System.out.println("服务状态为:terminated");
			}

			@Override
			public void failed(State from, Throwable failure) {
				synchTaskRunning = false;
				System.out.println("失败，cause：" + failure.getCause());
				try {
					SynchWebsocket.BroadCastInfo("同步失败，cause：" + failure.getCause());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}, MoreExecutors.directExecutor());
		synchTaskService.startAsync().awaitRunning();
		System.out.println("服务状态为:" + synchTaskService.state());
		return "开始同步数据";
	}

	/**
	 * 保存同步数据
	 * 
	 * @param synchData
	 * @return
	 */
	public boolean synchData(Map<String, Object> params) {
		ResponseEntity<ModelMap> response = restTemplate.postForEntity("http://" + cloudUrl + "/api/synch", params,
				ModelMap.class);
		HttpStatus statusCode = response.getStatusCode();
		if (!statusCode.is2xxSuccessful()) {
			throw new BusinessException("同步数据错误，请重试！");
		}

		ModelMap modelMap = response.getBody();
		if ((int) modelMap.get("httpCode") != 200) {
			throw new BusinessException(modelMap.get("msg").toString());
		}
		SynchData synchData = JSON.parseObject(JSON.toJSONString(modelMap.get("data")), new TypeReference<SynchData>() {
		});
		if (synchData == null) {
			throw new BusinessException("同步数据错误，请重试！");
		}
		if (synchData.getMapImages() != null && synchData.getMapImages().size() > 0) {
			ApplicationHome home = new ApplicationHome(getClass());
			File jarFile = home.getSource();
			for (MapImage mapImage : synchData.getMapImages()) {
				if (mapImage.getImagePath() != null) {
					String downloadUrl = "http://" + cloudUrl + mapImage.getImagePath();
					String savePath = jarFile.getParentFile().toString() + mapImage.getImagePath();
					String uploadPath = jarFile.getParentFile().toString() + File.separator + "uploads" + File.separator
							+ "images" + File.separator;
					try {
						downloadImage(downloadUrl, savePath, uploadPath);
					} catch (Exception e) {
						e.printStackTrace();
						//throw new BusinessException("同步地图图片错误，请重试！");
					}
				}
			}
		}
		synchMapper.truncateTable("equipment");
		equipmentService.saveBatch(synchData.getEquipments());

		synchMapper.truncateTable("equipment_pos");
		equipmentPosService.saveBatch(synchData.getEquipmentPos());

		synchMapper.truncateTable("image_map");
		mapImageService.saveBatch(synchData.getMapImages());

		synchMapper.truncateTable("security_materials");
		securityMaterialsService.saveBatch(synchData.getSecurityMaterials());

		synchMapper.truncateTable("t_permission");
		permissionService.saveBatch(synchData.getPermissions());

		synchMapper.truncateTable("t_role");
		roleService.saveBatch(synchData.getRoles());

		synchMapper.truncateTable("t_role_permission_ref");
		rolePermissionRefService.saveBatch(synchData.getRolePermissionRefs());

		synchMapper.truncateTable("t_teams");
		teamService.saveBatch(synchData.getTeams());

		synchMapper.truncateTable("t_user");
		userService.saveBatch(synchData.getUsers());

		synchMapper.truncateTable("t_user_role_ref");
		userRoleRefService.saveBatch(synchData.getUserRoleRefs());

		return true;
	}

	private void downloadImage(String downloadUrl, String savePath, String uploadPath) throws Exception {
		// 构造URL
		URL url = new URL(downloadUrl);
		// 打开连接
		URLConnection con = url.openConnection();
		// 设置请求超时为5s
		con.setConnectTimeout(5 * 1000);
		// 输入流
		InputStream is = con.getInputStream();
		// 1K的数据缓冲
		byte[] bs = new byte[1024];
		// 读取到的数据长度
		int len;
		File f = new File(uploadPath);
		if (!f.exists()) {
			f.mkdirs();
		}
		OutputStream os = new FileOutputStream(savePath);
		// 开始读取
		while ((len = is.read(bs)) != -1) {
			os.write(bs, 0, len);
		}
		// 完毕，关闭所有链接
		os.close();
		is.close();
	}

}
